package com.andryu.opengl.java

import android.content.Context
import android.opengl.GLES30
import com.andryu.base.LogUtils
import com.andryu.base.observer.OpenglJavaObserver
import com.andryu.opengl.utils.ShaderUtils
import dagger.hilt.android.qualifiers.ApplicationContext
import java.nio.ByteBuffer
import java.nio.ByteOrder
import java.nio.FloatBuffer
import java.nio.ShortBuffer
import javax.inject.Inject

class GraphicRectangleColorImpl @Inject constructor(@ApplicationContext private val context: Context) :
    OpenglJavaObserver {

    private val rectangleCoords = floatArrayOf(
        0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, // 右上角 红色
        0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, // 右下角 绿色
        -0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, // 左下角 蓝色
        -0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f  // 左上角 黄色
    )
    private val drawOrder = shortArrayOf(0, 1, 3, 1, 2, 3)
    private var vertexBuffer: FloatBuffer
    private var drawListBuffer: ShortBuffer
    private var shaderProgram: Int = 0

    private val vboIds = IntArray(1)
    private val iboIds = IntArray(1)

    init {
        //分配buffer
        val byteBuffer = ByteBuffer.allocateDirect(rectangleCoords.size * 4)
        byteBuffer.order(ByteOrder.nativeOrder())
        vertexBuffer = byteBuffer.asFloatBuffer()
        vertexBuffer.put(rectangleCoords)
        vertexBuffer.position(0)

        val dlb = ByteBuffer.allocateDirect( // (# of coordinate values * 2 bytes per short)
            drawOrder.size * 2
        )
        dlb.order(ByteOrder.nativeOrder())
        drawListBuffer = dlb.asShortBuffer()
        drawListBuffer.put(drawOrder)
        drawListBuffer.position(0)
    }

    override fun onSurfaceCreated() {
        //白色背景
        GLES30.glClearColor(1.0f, 1.0f, 1.0f, 1.0f)
        GLES30.glClearDepthf(1.0f)

        GLES30.glEnable(GLES30.GL_DEPTH_TEST)
        GLES30.glDepthFunc(GLES30.GL_LEQUAL)

        //2.加载shader, program
        shaderProgram = ShaderUtils.createProgram(
            context.assets,
            "shader/vertex/rectangleColor.glsl",
            "shader/fragment/rectangleColor.glsl"
        )
        LogUtils.d("createProgram shaderProgram = {?}", shaderProgram.toString())

        //3.生层vbo ibo
        GLES30.glGenBuffers(1, vboIds, 0)
        GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, vboIds[0])
        GLES30.glBufferData(
            GLES30.GL_ARRAY_BUFFER,
            rectangleCoords.size * 4,
            vertexBuffer,
            GLES30.GL_STATIC_DRAW
        )

        GLES30.glGenBuffers(1, iboIds, 0)
        GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER, iboIds[0])
        GLES30.glBufferData(
            GLES30.GL_ELEMENT_ARRAY_BUFFER,
            drawListBuffer.capacity() * 2,
            drawListBuffer,
            GLES30.GL_STATIC_DRAW
        )
    }

    override fun onSurfaceChanged(width: Int, height: Int) {

    }

    override fun onDrawFrame() {
        GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT or GLES30.GL_DEPTH_BUFFER_BIT)
        GLES30.glUseProgram(shaderProgram)

        val positionLoc = GLES30.glGetAttribLocation(shaderProgram, "vPosition")
        GLES30.glEnableVertexAttribArray(positionLoc)

        val colorLoc = GLES30.glGetAttribLocation(shaderProgram, "aColor")
        GLES30.glEnableVertexAttribArray(colorLoc)

        GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, vboIds[0])
        GLES30.glVertexAttribPointer(positionLoc, 3, GLES30.GL_FLOAT, false, 6 * 4, 0)

        GLES30.glVertexAttribPointer(colorLoc, 3, GLES30.GL_FLOAT, false, 6 * 4, 3 * 4)

        GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER, iboIds[0])

        GLES30.glDrawElements(GLES30.GL_TRIANGLES, drawOrder.size, GLES30.GL_UNSIGNED_SHORT, 0)

        GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER, 0)
        GLES30.glBindBuffer(GLES30.GL_TRIANGLES, 0)
        GLES30.glDisableVertexAttribArray(positionLoc)
        GLES30.glDisableVertexAttribArray(colorLoc)
    }

}